package com.higgins.eventtracking.client.health.action;

import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Logger;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyDownEvent;
import com.google.gwt.event.dom.client.KeyDownHandler;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Widget;
import com.higgins.eventtracking.client.EventTrackingService;
import com.higgins.eventtracking.client.EventTrackingServiceAsync;
import com.higgins.eventtracking.client.dto.TimeTableTaskDTO;
import com.higgins.eventtracking.client.genericcomponents.GenericColumn;
import com.higgins.eventtracking.client.genericcomponents.GenericColumns;
import com.higgins.eventtracking.client.genericcomponents.GenericTable;

public class DailyTable extends GenericTable	{
	private static final Logger log = Logger.getLogger(DailyTable.class.getName());
	private final EventTrackingServiceAsync greetingService = GWT
			.create(EventTrackingService.class);
	private Date storedDate = new Date();
	private Integer dayOfYear = null;
	private Integer periodOfFraction = 3;
	private Integer numberOfFractions = 5;
	private Integer numberOfDays = null;
	private List<List<TimeTableTaskDTO>> objectStore = new ArrayList<List<TimeTableTaskDTO>>();
	
	public DailyTable(GenericColumns genericColumns) {
		super(genericColumns);
		setColumnNames();
	}
	
	private void setColumnNames()	{
		greetingService.getDayOfYearNumber(storedDate, new AsyncCallback<Integer>() {
			@Override
			public void onFailure(Throwable caught) {
				
			}

			@Override
			public void onSuccess(Integer result) {
				dayOfYear = result;
			} } );
		int day = storedDate.getDay();
		((DailyColumns)genericColumns).initialiseColumns();
		if (day==0)	{
			((DailyColumns)genericColumns).addDay("Sunday");
			((DailyColumns)genericColumns).addDay("Monday");
			((DailyColumns)genericColumns).addDay("Tuesday");
			((DailyColumns)genericColumns).addDay("Wednesday");
			numberOfDays = 4;
		} else if (day == 1)	{
			((DailyColumns)genericColumns).addDay("Monday");
			((DailyColumns)genericColumns).addDay("Tuesday");
			((DailyColumns)genericColumns).addDay("Wednesday");
			((DailyColumns)genericColumns).addDay("Thursday");
			numberOfDays = 4;
		} else if (day == 2)	{
			((DailyColumns)genericColumns).addDay("Tuesday");
			((DailyColumns)genericColumns).addDay("Wednesday");
			((DailyColumns)genericColumns).addDay("Thursday");
			((DailyColumns)genericColumns).addDay("Friday");
			numberOfDays = 4;
		} else if (day == 3)	{
			((DailyColumns)genericColumns).addDay("Wednesday");
			((DailyColumns)genericColumns).addDay("Thursday");
			((DailyColumns)genericColumns).addDay("Friday");
			((DailyColumns)genericColumns).addDay("Saturday");
			numberOfDays = 4;
		} else if (day == 4)	{
			((DailyColumns)genericColumns).addDay("Thursday");
			((DailyColumns)genericColumns).addDay("Friday");
			((DailyColumns)genericColumns).addDay("Saturday");
			((DailyColumns)genericColumns).addDay("Sunday");
			numberOfDays = 4;
		} else if (day == 5)	{
			((DailyColumns)genericColumns).addDay("Friday");
			((DailyColumns)genericColumns).addDay("Saturday");
			((DailyColumns)genericColumns).addDay("Sunday");
			((DailyColumns)genericColumns).addDay("Monday");
			numberOfDays = 4;
		} else if (day == 6)	{
			((DailyColumns)genericColumns).addDay("Saturday");
			((DailyColumns)genericColumns).addDay("Sunday");
			((DailyColumns)genericColumns).addDay("Monday");
			((DailyColumns)genericColumns).addDay("Tuesday");
			numberOfDays = 4;
		}
		//listsLoaded();
	}
	public void listsLoaded()	{
		retrieveDTOs();
	}
	public void setDate(Date date)	{
		storedDate = date;
		setColumnNames();
		refresh();
	}
	public void retrieveDTOs()	{
		greetingService.retrieveTimeTableTasks(false, false, false, true, false, storedDate, new AsyncCallback<List<TimeTableTaskDTO>>()  {
			@Override
			public void onFailure(Throwable caught) {
				log.info("YearlyTimeTableTable: " + caught.toString());
			}

			@Override
			public void onSuccess(List<TimeTableTaskDTO> result) {
				loadData(convertDTOtoRowArray(result));
			}
		});		
	}
	private int getMonthNow()	{
		final DateTimeFormat yearFormat = DateTimeFormat.getFormat("M");
		final String month = yearFormat.format(new Date());
		return Integer.parseInt(month);
	}
	private boolean todaysDate(Date dateParam)	{
		Date theDateRightNow = new Date();
		final DateTimeFormat dayFormat = DateTimeFormat.getFormat("d");
		final DateTimeFormat monthFormat = DateTimeFormat.getFormat("M");
		final DateTimeFormat yearFormat = DateTimeFormat.getFormat("y");
		final String nowDay = dayFormat.format(theDateRightNow);
		final String dateDay = dayFormat.format(dateParam);
		final String nowMonth = monthFormat.format(theDateRightNow);
		final String dateMonth = monthFormat.format(dateParam);
		final String nowYear = yearFormat.format(theDateRightNow);
		final String dateYear = yearFormat.format(dateParam);
		
		return nowDay.equals(dateDay) && nowMonth.equals(dateMonth) && nowYear.equals(dateYear);
	}
	private List<List<Object>> convertDTOtoRowArray(List<TimeTableTaskDTO> timeTableTaskDTOs)	{
		List<List<Object>> rows = new ArrayList<List<Object>>();
		
		int dayCount = 0;
		int fractionOfDayCount = 0;
		List<Object> row = new ArrayList<Object>();
		List<String> fractionTimes = new ArrayList<String>();
		fractionTimes.add("6-9am");
		fractionTimes.add("9-12pm");
		fractionTimes.add("12-3pm");
		fractionTimes.add("3-6pm");
		fractionTimes.add("6-9pm");
		fractionTimes.add("9-12pm");
		
		row.add("0");
		row.add(fractionTimes.get(fractionOfDayCount));
		
		List<TimeTableTaskDTO> subObjectStore = new ArrayList<TimeTableTaskDTO>();
		
		Iterator<TimeTableTaskDTO> iterator = timeTableTaskDTOs.iterator();
		
		while (iterator.hasNext())		{
			TimeTableTaskDTO dto = iterator.next();
			while (dto.getDayFraction() > fractionOfDayCount)	{
				while (dayCount <= (numberOfDays-1))	{
					row.add("");
					subObjectStore.add(null);
					dayCount++;
				}
				if (dayCount >= (numberOfDays-1))	{
					dayCount = 0;
					fractionOfDayCount++;
					objectStore.add(subObjectStore);
					subObjectStore = new ArrayList<TimeTableTaskDTO>();

					rows.add(row);
					row = new ArrayList<Object>();
					row.add("0");
					row.add(fractionTimes.get(fractionOfDayCount));
				}
			}
			if (dto.getDayFraction() == fractionOfDayCount)		{
				while (dto.getDayOfYear() > (dayOfYear + dayCount))	{
					row.add("");
					subObjectStore.add(null);
					dayCount++;
				}
				if (dto.getDayOfYear() == (dayOfYear + dayCount))	{
					row.add(dto.getTask());
					subObjectStore.add(dto);
					dayCount++;
				}
			}
		}
		while (fractionOfDayCount <= numberOfFractions)	{
			while (dayCount <= (numberOfDays-1))	{
				row.add("");
				subObjectStore.add(null);
				dayCount++;
			}
			rows.add(row);
			objectStore.add(subObjectStore);
			subObjectStore = new ArrayList<TimeTableTaskDTO>();
			dayCount=0;
			fractionOfDayCount++;
			if (fractionOfDayCount <= numberOfFractions) 	{
				row = new ArrayList<Object>();
				row.add("0");
				row.add(fractionTimes.get(fractionOfDayCount));
			}
		}
		return rows;
	}
	protected void addObject(int row, int column, Object object)	{
		ensureRowAvailable(row);
		GenericColumn genericColumn = genericColumns.getColumn(column);
//		if (genericColumn.getType().equals(JobSiteDTO.class))	{
//			addJobSiteDTO(row, column, object, genericColumn);
	}
	
	public void updateItemCell(int row, int column)	{
		TimeTableTaskDTO dto = new TimeTableTaskDTO();
		dto.setId(getTimeTableId(row, column));
		dto.setDayFraction(row - 1);
		dto.setDayOfYear(dayOfYear + column -2);
		dto.setTask(getText(row, column));
		dto.setDate(storedDate);
		updateRow(dto);
	}
	private Long getTimeTableId(int row, int column)	{
		List<TimeTableTaskDTO> dtoList = objectStore.get(row-1);
		if (dtoList==null)	
			return null;
		for (TimeTableTaskDTO dto:dtoList)	{
			if (dto!=null )	{
				if (dto.getDayOfYear().equals(dayOfYear+column-2))	{
					return dto.getId();
				}
			} 
		}
		return null;
	}
	private Integer getMonthFromText(String timeText)	{
//		if (timeText.contains(":"))	{
//			int location = timeText.indexOf(":");
//		String hourText = timeText.substring(0, location);
		String yearText = timeText;
		return Integer.parseInt(yearText);
//		}
//		return null;
	}
	private void updateRow(TimeTableTaskDTO dto)	{
		try {
			greetingService.updateTimeTableTask(dto, new AsyncCallback<String>()	{
					@Override
					public void onFailure(Throwable caught) {
						log.info("YearlyTimeTableTable: " + caught.toString());
					}

					@Override
					public void onSuccess(String result) {
//						setRowIdAfterUpdate(result);
					}
				});
		} catch (IllegalArgumentException e) {
			log.info("HealthAlertTable: " + e.toString());
		} /*catch (SecurityAccessDeniedException e) {
			log.info("SecurityAccessDeniedException: " + e.toString());
		} 		*/
	}
	
	protected void makeGenericCellEditable(GenericColumn genericColumn, final int row, final int column)	{
		Widget widget = getWidget(row, column);
		if (widget!=null && widget.getClass().equals(TextBox.class))	{
			return;
		}
		final TextBox textBox = new TextBox();
		textBox.setText(getText(row, column));
		textBox.setFocus(true);
		textBox.setCursorPos(0);
		setWidget(row, column, textBox);
		textBox.setWidth(genericColumn.getWidth()+"px");
		textBox.addKeyDownHandler(new KeyDownHandler() {

			@Override
			public void onKeyDown(KeyDownEvent event) {
				// TODO Auto-generated method stub
				int code = event.getNativeKeyCode();
				if (KeyCodes.KEY_ENTER == code || KeyCodes.KEY_TAB == code)	{
					setWidget(row, column, new Label(textBox.getText()));
					setRowUpdateTag(row);
					updateItemCell(row);
					updateItemCell(row, column);
					if (row < 6)	{
						makeTableEditable((row + 1), column);
					}
				}
				if (KeyCodes.KEY_ESCAPE == code)	{
					setWidget(row, column, new Label(textBox.getText()));
				}
			}
		});
		textBox.setFocus(true);
	}	
}
